home *** CD-ROM | disk | FTP | other *** search
/ Workbench Design / WB Collection.iso / workbench werkzeuge / scherz programme / fortune / source / readfort.c < prev    next >
C/C++ Source or Header  |  1996-04-07  |  36KB  |  1,569 lines

  1. /*  Source Control
  2. $RCS
  3.  
  4. $version 3.25
  5.  
  6. $date Wed Mar 03 17:53:36 1993
  7.  
  8. $changes :
  9.  
  10. Revision 3.25    Jim Wed Mar 03 17:53:36 1993
  11. Rewrote the QUIT stuff for Brian Sutherland
  12.  
  13. Revision 3.24    Jim Wed Jul 15 00:47:06 1992
  14. Faster disk access, and priority niced up during disk acess/decompression
  15.  
  16. Revision 3.23    Jim Mon Mar 16 14:13:22 1992
  17. Supports reqtools.library
  18.  
  19. Revision 3.22    Jim Fri Dec 06 18:01:04 1991
  20. Alarm clock added
  21.  
  22. Revision 3.21    Jim Fri Dec 06 12:10:30 1991
  23. Clock/memory monitor functions added
  24.  
  25. Revision 3.20    Jim Thu Dec 05 21:24:08 1991
  26. Timer device supported
  27.  
  28. Revision 3.19    Jim Thu Dec 05 19:23:31 1991
  29. Pause and Iconify gadgets added
  30.  
  31. Revision 3.18    Jim Mon Oct 14 12:16:59 1991
  32. Gadgets added (registered users only!!)
  33.  
  34. Revision 3.17    Jim Wed Aug 14 16:00:54 1991
  35. -q and QUIT options added (suggested by D.R. Daines)
  36.  
  37. Revision 3.16    Jim Sun Aug 11 15:15:44 1991
  38. Ftext bug fixed- reads extended ascii
  39.  
  40. Revision 3.15    Jim Wed Aug 07 18:47:44 1991
  41. Restored
  42.  
  43. Revision 3.14    Jim Wed Aug 07 18:12:03 1991
  44. Special version
  45.  
  46. Revision 3.13    Jim Wed Aug 07 18:07:23 1991
  47. No change
  48.  
  49. Revision 3.12    Jim Sun Aug 04 03:05:49 1991
  50. bug in WriteFortune fixed. Used to crash if device not mounted.
  51.  
  52. Revision 3.11    Jim Wed Jul 17 15:23:15 1991
  53. bug fixed with long flags
  54.  
  55. Revision 3.10    Jim Tue Jul 16 15:19:29 1991
  56. Fortune number can be specified (suggested by Leigh Barlow)
  57.  
  58. Revision 3.9    Jim Sun Jul 14 15:23:00 1991
  59. Better error handling - error window opened if on WB
  60.  
  61. Revision 3.8    Jim Tue Jul 09 18:16:56 1991
  62. -x and -y flags added, -p kept for compatability
  63.  
  64. Revision 3.7    Jim Sat Jun 29 22:10:28 1991
  65. Adaptive huffman code used
  66.  
  67. Revision 3.6    Jim Tue Jun 11 15:02:43 1991
  68. coloured backgrounds (oh dear.. what is this, gfortune?)
  69.  
  70. Revision 3.5    Jim Tue Jun 11 14:41:03 1991
  71. Now allows for WB larger than normal.
  72.  
  73. Revision 3.4    Jim Sat Jun 01 20:34:35 1991
  74. Now fortunes printed directly with graphics drivers (AF Coverdisk version)
  75.  
  76. Revision 3.3    Jim Sat Jun 01 20:34:14 1991
  77. More tidying up
  78.  
  79. Revision 3.2    Jim Sat Jun 01 10:33:28 1991
  80. various tidying up, width support, fonts etc.
  81.  
  82. Revision 3.1    Jim Fri May 31 13:29:21 1991
  83. tooltypes DELAY and FLAGS added
  84.  
  85. Revision 3.0    Jim Fri May 31 12:20:37 1991
  86. speak, print and key support; plus better help.
  87.  
  88. Revision 2.2    Jim Fri May 31 11:40:18 1991
  89. Now with WB interface
  90.  
  91. Revision 2.1    Jim Thu May 23 21:09:52 1991
  92. Now works under 2.0
  93.  
  94. Revision 2.0    Jim Mon Sep 10 19:22:17 1990
  95. Added to RCS
  96.  
  97. */
  98.  
  99. /*
  100.     Fortune Cookie Printer. Takes cookies from a file given in the
  101.     command line, or "fortunes" if no file is given. The file
  102.     is in the format produced by makefort.
  103.  
  104.     Written by J. Finnis, 1990-1991.
  105. */
  106.  
  107. #include <exec/types.h>
  108. #include <exec/memory.h>
  109. #include <intuition/intuition.h>
  110. #include <graphics/gfxbase.h>
  111. #include <workbench/workbench.h>
  112. #include <workbench/startup.h>
  113. #include <libraries/dos.h>
  114. #include <libraries/reqtools.h>
  115. #include <devices/timer.h>
  116. #include <devices/audio.h>
  117. #include <proto/all.h>
  118. #include <proto/reqtools.h>
  119.  
  120. #include <stdio.h>
  121. #include <stdlib.h>
  122. #include <string.h>
  123. #include <math.h>
  124. #include <stdarg.h>
  125. #include <time.h>
  126.  
  127. #define TIMELIM    10
  128. #define ICONLEN        350
  129. #define ICONTITLE    "Fortune 3.25 by J.Finnis"
  130. #define    MINWIDTH    350
  131. #define    TINYICONLEN    160
  132. #define    CLOCKLEN    150
  133.  
  134. #define MAXSIZE    1000
  135. #define    XOFFSET    (MINWIDTH-125)
  136. #define    TINYXOFFSET    21
  137.  
  138. #define    CF_CLOCK    1    /* show time */
  139. #define    CF_TOTALMEM    2    /* show total memory */
  140. #define    CF_ALLMEM    4    /* show memory as chip/fast */
  141. #define    CF_DATE        8    /* show date */
  142.  
  143. static char *month_names[]=
  144. {
  145.     "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct",
  146.     "Nov","Dec"
  147. };
  148.  
  149. static UBYTE whichannel[]={1,2,4,8};
  150. static struct IOAudio *AIOPtr=NULL;
  151. static struct MsgPort *audioport=NULL;
  152.  
  153. #define    SOUND_LEN    934
  154.  
  155. static UWORD chip SoundData[]={
  156. 0x0,0x0,0x800,0xee,0xf2eb,0xf5f2,0xebf0,0xebe5,
  157. 0xf1f5,0xf901,0x507,0x909,0xe0e,0x1214,0xc07,0x1210,
  158. 0x1926,0x1a22,0x2415,0x1d14,0xc0e,0x404,0xfffc,0xfef4,
  159. 0xf1f1,0xecec,0xe8e2,0xe1de,0xe0dc,0xe2ec,0xeefb,0xfd02,
  160. 0x1117,0x14fb,0xdfd5,0xc1b6,0xc9e9,0xf909,0x1d1a,0x1b26,
  161. 0x3c5b,0x6670,0x7736,0x6e8,0xb0b4,0xc5dc,0x212,0x222e,
  162. 0x1b1b,0x1cfd,0xf4f0,0xd4d2,0xdcdc,0xebf3,0xf9f9,0xeee2,
  163. 0xc380,0x8299,0xc104,0x6d7f,0x7f7f,0x6f0d,0xdbc5,0xd7d4,
  164. 0xdf04,0xf2f7,0x2841,0x4d73,0x4c1b,0xe6b9,0xb5b9,0xd9fd,
  165. 0x151a,0x2925,0xfff2,0xe5b5,0x8f81,0x8294,0xca12,0x7f7f,
  166. 0x7f7f,0x2fc6,0x8e91,0xcad1,0xef1a,0x2f49,0x637f,0x501a,
  167. 0xf5c1,0xa9cf,0xfa02,0x1926,0x1f14,0x80a,0xfbea,0xc783,
  168. 0x8182,0x9bfa,0x747f,0x7f7f,0x12af,0x8083,0xb706,0x232f,
  169. 0x3c4e,0x5262,0x5f19,0xd6b7,0xc0d3,0x92d,0x261a,0x4fc,
  170. 0xfffc,0x1717,0xec95,0x8082,0x8dda,0x6c7f,0x7f71,0xea8e,
  171. 0x8182,0xc61a,0x3627,0x2c37,0x4475,0x6733,0xddaa,0xb7cc,
  172. 0x1742,0x3c1f,0xfef4,0xe80b,0x2828,0x17b4,0x8083,0x83d3,
  173. 0x607f,0x7f7e,0xf880,0x8483,0xe329,0x3a28,0x112f,0x5278,
  174. 0x6a32,0xd596,0xb1db,0x2753,0x471a,0xe7dc,0xde06,0x2730,
  175. 0x1fbf,0x8082,0x85da,0x5e7f,0x7f62,0xd580,0x8bab,0x739,
  176. 0x2905,0xf922,0x4660,0x520f,0xb58d,0xbdf9,0x324c,0x32f7,
  177. 0xcbd6,0xea10,0x2f31,0xb9c,0x8083,0x9d03,0x7f7f,0x7f2c,
  178. 0x9d80,0x9ae4,0x2b3d,0x1d06,0xd32,0x5a65,0x27e2,0xab9d,
  179. 0xe92a,0x5841,0x16de,0xb7e4,0x221,0x3228,0xd780,0x818d,
  180. 0xc249,0x7f7f,0x5fce,0x8095,0xc71f,0x4824,0xc0d,0x2056,
  181. 0x6957,0xf4b8,0xa8d2,0x1557,0x591c,0xeec3,0xd600,0x2c38,
  182. 0x2cf4,0x8480,0x82be,0x277f,0x7f74,0xea8d,0x9ac7,0x955,
  183. 0x3901,0x61a,0x3d5c,0x6a13,0xc3af,0xccfe,0x4863,0x3bf1,
  184. 0xcddb,0xf129,0x433b,0x697,0x8083,0xa30e,0x7f7f,0x79f0,
  185. 0x8290,0xcaff,0x5444,0x5e7,0xb37,0x4b69,0x23c3,0x96b5,
  186. 0xff35,0x5e45,0xeabc,0xc3ee,0x2242,0x4a19,0xa180,0x839f,
  187. 0x77d,0x7f6f,0xe881,0x88c7,0x24e,0x3d0c,0xe80b,0x434f,
  188. 0x5830,0xcb97,0xb8fe,0x3360,0x4d00,0xc1c4,0xe815,0x444f,
  189. 0x29b2,0x8083,0x8cf5,0x787f,0x76f2,0x8080,0xafee,0x3f34,
  190. 0x12f2,0x237,0x455e,0x33e1,0xa2ab,0xf11f,0x4f59,0x18da,
  191. 0xccdd,0x630,0x4a36,0xe580,0x8087,0xe45c,0x7f7f,0x31a8,
  192. 0x85b8,0xd728,0x3b1a,0xf702,0x3444,0x5033,0x4bc,0xbdea,
  193. 0x1237,0x3d21,0xebcf,0xe2ff,0x1f33,0x33f5,0x8480,0x85d3,
  194. 0x3a7f,0x7f4a,0xc98a,0xb4cc,0x1835,0x3208,0x35,0x383e,
  195. 0x4011,0xd0af,0xe305,0x284c,0x3cfb,0xcfd9,0xef11,0x3d44,
  196. 0x16b0,0x8083,0xac07,0x777f,0x6ef8,0x848d,0xaef2,0x3336,
  197. 0x21e9,0xff1f,0x3048,0x2af2,0xb3ad,0xde0e,0x3e47,0x22dc,
  198. 0xc0da,0xff28,0x3e31,0xee89,0x8083,0xd439,0x7f7f,0x48bd,
  199. 0x80a2,0xc313,0x413d,0xfe8,0x1123,0x3c3f,0x1ff1,0xadc9,
  200. 0xec17,0x322c,0x19dc,0xd5eb,0x420,0x2928,0xe084,0x8191,
  201. 0xed45,0x7f7f,0x3cc2,0x93b2,0xcb10,0x2f3b,0x14ff,0x2420,
  202. 0x3131,0x1bf2,0xd5ed,0xfc17,0x2b28,0xeed,0xedee,0x621,
  203. 0x2926,0xe48a,0x819f,0xed44,0x7f7d,0x44d7,0xb2b5,0xc8fe,
  204. 0x1533,0x160f,0x2415,0x1e19,0x12fc,0xec03,0x717,0x1c15,
  205. 0x6ec,0xedf1,0x213,0x1919,0xf3ab,0x81b8,0xef2c,0x667a,
  206. 0x5b08,0xdcc1,0xb4d6,0xe70d,0xd19,0x2a1d,0x150c,0x7f7,
  207. 0xe6f9,0xf4f8,0xfcfd,0xfefd,0x403,0x305,0xf2eb,0xdfb6,
  208. 0x95cb,0xf315,0x4660,0x602c,0xfef6,0xe6f0,0xfa04,0x40c,
  209. 0x2016,0x909,0xb10,0x80f,0xafd,0xf3e5,0xdce9,0xf7fe,
  210. 0xb0d,0x3f5,0xddd5,0xe8f5,0xa1c,0x251f,0x1504,0xf0e8,
  211. 0xf2ff,0x40d,0x1303,0xfc00,0x203,0x106,0xc03,0x311,
  212. 0x1914,0x120e,0x40c,0x904,0xa09,0x309,0xd06,0x609,
  213. 0xd07,0x8,0x1200,0xf805,0xd07,0x806,0x20b,0x703, 0xa0c,0x0,0x0,0x0
  214. };
  215.  
  216. int colour=0;
  217. int Again=FALSE;
  218. int Ticks=0,back=0,speak=0,print=0,longflag=0,win=0;
  219. int del=-1,clockpos;
  220. int iy,ix=300,tiny=0;
  221. ULONG clock=0L;
  222. LONG olddir=-1;
  223. char *internal="Internal error: %d\n";
  224. char *Version="Fortune vrsn 3.25 by Jim Finnis, Mar 1993\n";
  225.  
  226. struct TextFont *topazfont,*sysfont,*customfont=NULL;
  227.  
  228. #define IDCMPFLAGS GADGETDOWN|VANILLAKEY|NEWSIZE|CLOSEWINDOW
  229.  
  230. static UWORD chip LeftGadgData[]={
  231. 0xffff,0xffff,0xefff,0xc001,0x8001,
  232. 0x8001,0xc001,0xefff,0xffff,0xffff,
  233. 0xf7ff,0xe7ff,0xc000,0x8000,0x0,
  234. 0x0,0x8000,0xc000,0xe7ff,0xf7ff
  235. };
  236. static UWORD chip RandGadgData[]={
  237. 0xffff,0x8001,0x9c71,0x8209,0x8c31,
  238. 0x8001,0x8821,0x8001,0x8001,0xffff,
  239. 0x0,0x0,0x0,0x0,0x0,
  240. 0x0,0x0,0x0,0x0,0x0
  241. };
  242. static UWORD chip RightGadgData[]={
  243. 0xffff,0xffff,0xfff7,0x8003,0x8001,
  244. 0x8001,0x8003,0xfff7,0xffff,0xffff,
  245. 0xffef,0xffe7,0x3,0x1,0x0,
  246. 0x0,0x1,0x3,0xffe7,0xffef
  247. };
  248.  
  249. static UWORD chip IconifyGadgData[]={
  250. 0x7ffe,0x7ffe,0x6e76,0x6246,0x6006,
  251. 0x6006,0x6246,0x6e76,0x7ffe,0x7ffe,
  252. 0x0,0x0,0x0,0x0,0x0,
  253. 0x0,0x0,0x0,0x0,0x0
  254. };
  255.  
  256. static UWORD chip PauseGadgData[]={
  257. 0x7ffe,0x7ffe,0x783e,0x799e,0x799e,
  258. 0x783e,0x79fe,0x79fe,0x7ffe,0x7ffe,
  259. 0x0,0x0,0x0,0x0,0x0,
  260. 0x0,0x0,0x0,0x0,0x0
  261. };
  262.  
  263. static struct Image RandImage={0,0,16,10,2,RandGadgData,3,0,NULL};
  264. static struct Image RightImage={0,0,16,10,2,RightGadgData,3,0,NULL};
  265. static struct Image LeftImage={0,0,16,10,2,LeftGadgData,3,0,NULL};
  266. static struct Image PauseImage={0,0,16,10,2,PauseGadgData,3,0,NULL};
  267. static struct Image IconifyImage={0,0,16,10,2,IconifyGadgData,3,0,NULL};
  268.  
  269. static struct Gadget RightGadg={NULL,0,0,16,10,
  270. GADGIMAGE|GADGHCOMP,RELVERIFY|GADGIMMEDIATE|TOPBORDER,
  271. BOOLGADGET,(APTR)&RightImage,NULL,NULL,NULL,
  272. NULL,2,NULL};
  273. static struct Gadget RandGadg={&RightGadg,0,0,16,10,
  274. GADGIMAGE|GADGHCOMP,RELVERIFY|GADGIMMEDIATE|TOPBORDER,
  275. BOOLGADGET,(APTR)&RandImage,NULL,NULL,NULL,
  276. NULL,1,NULL};
  277. static struct Gadget PauseGadg={&RandGadg,0,0,16,10,
  278. GADGIMAGE|GADGHCOMP,TOGGLESELECT|RELVERIFY|GADGIMMEDIATE|TOPBORDER,
  279. BOOLGADGET,(APTR)&PauseImage,NULL,NULL,NULL,
  280. NULL,3,NULL};
  281. static struct Gadget IconifyGadg={&PauseGadg,0,0,16,10,
  282. GADGIMAGE|GADGHCOMP,RELVERIFY|GADGIMMEDIATE|TOPBORDER,
  283. BOOLGADGET,(APTR)&IconifyImage,NULL,NULL,NULL,
  284. NULL,4,NULL};
  285. static struct Gadget LeftGadg={&IconifyGadg,0,0,16,10,
  286. GADGIMAGE|GADGHCOMP,RELVERIFY|GADGIMMEDIATE|TOPBORDER,
  287. BOOLGADGET,(APTR)&LeftImage,NULL,NULL,NULL,
  288. NULL,0,NULL};
  289.  
  290. static struct NewWindow ConNewWindow=
  291. {
  292.     0,0,        /*Window posn*/
  293.     0,0,        /*Width+height*/
  294.  
  295.     -1,-1,        /*detailpen, blockpen*/
  296.     IDCMPFLAGS,
  297.     NOCAREREFRESH|SMART_REFRESH|ACTIVATE|WINDOWCLOSE|
  298.         WINDOWDEPTH|WINDOWDRAG,
  299.     NULL,        /* first gadget (we add them with AddGList()) */
  300.     NULL,        /*checkmark*/
  301.     NULL,        /*window title*/
  302.     NULL,        /*screen*/
  303.     NULL,        /*bitmap*/
  304.     120,50,        /*minsize*/
  305.     640,200,    /*maxsize*/
  306.     WBENCHSCREEN
  307. };
  308.  
  309. extern void loadhuffman(BPTR);
  310. extern char *uncompress(char *);
  311. extern long readlong(BPTR);
  312. extern void readstring(char *,int,BPTR);    /* buf len file */
  313.  
  314. char *infile="fortunes";
  315.  
  316. struct IntuitionBase *IntuitionBase=NULL;
  317. struct GfxBase *GfxBase=NULL;
  318. struct ReqToolsBase *ReqToolsBase=NULL;
  319. struct Library *IconBase=NULL;
  320. struct Library *DiskfontBase=NULL;
  321.  
  322. VOID CreateConsole();
  323. VOID CleanUpAndExit();
  324.  
  325. struct Screen *ConsoleScreen=NULL;
  326. struct Window *ConsoleWindow=NULL;
  327.  
  328. LONG ConsoleOpen=FALSE;
  329.  
  330. int CXBRK(VOID)
  331. {
  332.     return(0);
  333. }
  334.  
  335. int wb_exec=1;
  336. static int stolen=0,req=0;
  337.  
  338. static long old_priority=0;
  339. #define    HIGH_PRI    3
  340.  
  341. void NiceUp(void)
  342. {
  343.     old_priority=SetTaskPri(FindTask(NULL),HIGH_PRI);
  344. }
  345. void NiceDown(void)
  346. {
  347.     SetTaskPri(FindTask(NULL),old_priority);
  348. }
  349.  
  350. void Panic(int fatal,char *s,...)
  351. {
  352.     va_list argptr;
  353.     char buf[80];
  354.     FILE *a;
  355.  
  356.     va_start(argptr,s);
  357.     vsprintf(buf,s,argptr);
  358.     va_end(argptr);
  359.  
  360.     NiceDown();
  361.     if(win)
  362.     {
  363.         if(ReqToolsBase)
  364.         {
  365.             rtEZRequest(buf,"Oh dear",NULL,NULL);
  366.         }
  367.         else
  368.         {
  369.             if(a=fopen("CON:0/0/640/40/Message","r+"))
  370.             {
  371.                 fprintf(a,buf);
  372.                 Delay(3*TICKS_PER_SECOND);
  373.                 fclose(a);
  374.             }
  375.         }
  376.     }
  377.     else
  378.     {
  379.         if(a=fopen("*","r+"))
  380.         {
  381.             fputs(buf,a);
  382.             fclose(a);
  383.         }
  384.     }
  385.     if(fatal)CleanUpAndExit();
  386. }
  387.  
  388. /*
  389.  * Audio stuff for the alarm
  390.  *
  391.  */
  392.  
  393. static void SND_Ready(void)
  394. {
  395.     if(AIOPtr)    /* If there's an IO running, abort it */
  396.     {
  397.         if(req && !CheckIO((struct IORequest *)AIOPtr))
  398.         {
  399.             AbortIO((struct IORequest *)AIOPtr);
  400.             Wait(1L << audioport->mp_SigBit);
  401.         }
  402.         if(GetMsg(audioport))    /* if there's a reply waiting */
  403.         {
  404.             switch(AIOPtr->ioa_Request.io_Error) /* check for error */
  405.             {
  406.                 case 0:    /* No error */
  407.                 break;
  408.             case ADIOERR_NOALLOCATION:
  409.                 stolen=1;
  410.                 break;
  411.             default:
  412.                 Panic(1,"bad channel audio command reply");
  413.             }
  414.         }
  415.         req=0;
  416.     }
  417. }
  418.  
  419. static ULONG device=1;
  420. static long clockfreq;
  421.  
  422. static void SND_Shutdown(void)
  423. {
  424.     SND_Ready();
  425.     if(audioport)DeletePort(audioport);
  426.     if(!device)CloseDevice((struct IORequest *)AIOPtr);
  427.     if(AIOPtr)FreeMem(AIOPtr,sizeof(struct IOAudio));
  428. }
  429.  
  430. static void SND_SetupAllocate(void)
  431. {
  432.      AIOPtr->ioa_Request.io_Message.mn_ReplyPort=audioport;
  433.  
  434.     /* Priority 70 is above most stuff, but still below the MEDplayer
  435.     (which is 127) */
  436.  
  437.     AIOPtr->ioa_Request.io_Message.mn_Node.ln_Pri=70;
  438.     AIOPtr->ioa_Request.io_Command=ADCMD_ALLOCATE;
  439.     AIOPtr->ioa_Request.io_Flags=ADIOF_NOWAIT;
  440.     AIOPtr->ioa_AllocKey=0;
  441.     AIOPtr->ioa_Data=whichannel;
  442.     AIOPtr->ioa_Length=sizeof(whichannel);
  443. }
  444.  
  445. static int SND_ReAllocate(void)
  446. {
  447.     SND_SetupAllocate();
  448.     stolen=0;
  449.     return(DoIO((struct IORequest *)AIOPtr));
  450. }
  451.  
  452.  
  453. static void SND_Init(void)
  454. {
  455.     if(!GfxBase)Panic(1,"sound: wot no GfxBase?")
  456.     clockfreq= (GfxBase->DisplayFlags & PAL) ? 3546895 : 3579545;
  457.     if(!(audioport=CreatePort(0,0)))Panic(1,"sound: can't allocate port");
  458.     if(!(AIOPtr=AllocMem(sizeof(struct IOAudio),MEMF_CLEAR|MEMF_PUBLIC)))
  459.         Panic(1,"sound: can't allocate iorequest");
  460.  
  461.     SND_SetupAllocate();
  462.  
  463.     if(device=OpenDevice("audio.device",0L,(struct IORequest *)AIOPtr,0L))
  464.         Panic(1,"can't open audio device");
  465. }
  466.  
  467. void SND_Play(char *data,ULONG len,int period)
  468. {
  469.     /* This is the PLAY function */
  470.  
  471.     SND_Ready();    /* abort any running sound and pending replies */
  472.  
  473.     /* Check if our channel was stolen last time */
  474.  
  475.     if(stolen)    /* Attempt to reallocate */
  476.     {
  477.         if(SND_ReAllocate())return;
  478.     }
  479.  
  480.     AIOPtr->ioa_Request.io_Message.mn_ReplyPort    =audioport;
  481.     AIOPtr->ioa_Request.io_Command=CMD_WRITE;
  482.     AIOPtr->ioa_Request.io_Flags=ADIOF_PERVOL;
  483.     AIOPtr->ioa_Data=data;
  484.     AIOPtr->ioa_Length=len;
  485.     AIOPtr->ioa_Period=period;
  486.     AIOPtr->ioa_Volume=64;
  487.     AIOPtr->ioa_Cycles=1;
  488.     BeginIO((struct IORequest *)AIOPtr);
  489.     req=1;
  490. }
  491.  
  492.  
  493. /*
  494.  *    Version 3.20 : Timer device stuff.
  495.  *
  496.  */
  497.  
  498. struct timerequest *timermsg=NULL;
  499. struct MsgPort *timerport=NULL;
  500. int timeropen=0;
  501.  
  502. /* Set up a 1 second timer request */
  503. void TimerGo(void)
  504. {
  505.     timermsg->tr_node.io_Command=TR_ADDREQUEST;
  506.     timermsg->tr_time.tv_secs=1;
  507.     timermsg->tr_time.tv_micro=0;
  508.     timermsg->tr_node.io_Message.mn_ReplyPort=timerport;
  509.  
  510.     SendIO((struct IORequest *)timermsg);
  511. }
  512.  
  513. /* Allocate and open the timer device, and fire off the first 1 second
  514. request. */
  515. void StartTimerDevice(void)
  516. {
  517.     if(!(timermsg=(struct timerequest *)
  518.         AllocMem(sizeof(struct timerequest),MEMF_PUBLIC|MEMF_CLEAR)))
  519.         Panic(1,"no memory for time request");
  520.  
  521.     timermsg->tr_node.io_Message.mn_Node.ln_Type=NT_MESSAGE;
  522.     timermsg->tr_node.io_Message.mn_Node.ln_Pri=0;
  523.     timermsg->tr_node.io_Message.mn_Node.ln_Name=NULL;
  524.  
  525.     if(OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)timermsg,0))
  526.         Panic(1,"unable to open timer device");
  527.     timeropen=1;
  528.     if(!(timerport=CreatePort(0,0)))
  529.         Panic(1,"unable to open timer port");
  530.  
  531.     /* Fire off the first request */
  532.  
  533.     TimerGo();
  534. }
  535.  
  536. void TimerStop(void)
  537. {
  538.     if(timerport && !CheckIO((struct IORequest *)timermsg))
  539.     {
  540.         AbortIO((struct IORequest *)timermsg);
  541.         WaitIO((struct IORequest *)timermsg);
  542.     }
  543.  
  544.     if(timerport)DeletePort(timerport);
  545.     if(timeropen)CloseDevice((struct IORequest *)timermsg);
  546.     if(timermsg)FreeMem(timermsg,sizeof(struct timerequest));
  547. }
  548.  
  549. /*
  550.  *
  551.  *
  552.  */
  553.  
  554. int GetTextLength(struct TextFont *t,char *s)
  555. {
  556.     UWORD width=0;
  557.     char c;
  558.     int addkern,addspace,kern,space;
  559.  
  560.     addkern = t->tf_CharKern ? TRUE : FALSE;
  561.     addspace= t->tf_CharSpace ? TRUE : FALSE;
  562.  
  563.     for(;*s;s++)
  564.     {
  565.         c= *s-t->tf_LoChar;
  566.         kern=((UWORD *)(t->tf_CharKern))[c];
  567.         space=((UWORD *)(t->tf_CharSpace))[c];
  568.         if(addspace)
  569.             width+=space;
  570.         else
  571.             width+=t->tf_XSize;
  572.         if(addkern)
  573.             width+=kern;
  574.     }
  575.     width+=5;
  576.     return((int)width);
  577. }
  578.  
  579. int GetMaxTextLen(struct TextFont *font,char *str)
  580. {
  581.     char *i,*j;
  582.     int t1=0,t2;
  583.  
  584.     for(i=str,j=str;;j++)
  585.     {
  586.         if(*j=='\n'||!*j)
  587.         {
  588.             char c;
  589.  
  590.             c=*j; *j=0;
  591.             t2=GetTextLength(font,i);
  592.             t1=max(t2,t1);
  593.             if(!(*(i=j)=c))break;
  594.             i++;
  595.         }
  596.     }
  597.     return(t1);
  598. }
  599.  
  600. void PrintUsage(void)
  601. {
  602.     FILE *a;
  603.     char buf[10];
  604.  
  605.     if(!(a=fopen("*","r+")))CleanUpAndExit();
  606.     fprintf(a,Version);
  607. fprintf(a,"Command line options:\n");
  608. fprintf(a,"-f<file>    read fortunes from <file>\n");
  609. fprintf(a,"-l          long fortunes (>5 lines) only\n");
  610. fprintf(a,"-w          start program up in its own window\n");
  611. fprintf(a,"-s          say the fortune with the speech synthesizer\n");
  612. fprintf(a,"options only valid when -w is also used:\n");
  613. fprintf(a,"-i          start program up as an icon\n");
  614. fprintf(a,"-t          use a tiny form of the icon\n");
  615. fprintf(a,"-n<number>  display fortune <number>\n");
  616. fprintf(a,"-d<number>  delay for <number> seconds between each fortune\n");
  617. fprintf(a,"-x<number>  put the window at <number> pixels across\n");
  618. fprintf(a,"-y<number>  put the window at <number> pixels down the screen\n");
  619. fprintf(a,"-p<number>  as above - kept for compatibility\n");
  620. fprintf(a,"-c<number>  set background colour (good in WB2.0!)\n");
  621. fprintf(a,"-m<number>  maximum size of window <number> pixels high\n");
  622. fprintf(a,"-o[dcmt]    set up the clock display:\n");
  623. fprintf(a,"                   d - display the date\n");
  624. fprintf(a,"                   c - display the time\n");
  625. fprintf(a,"                   m - display available CHIP and FAST memory\n");
  626. fprintf(a,"                   t - display total available memory\n");
  627. fprintf(a,"-q          quit after a delay\n");
  628. fprintf(a,"\nKeys when the fortune window is active:\n");
  629. fprintf(a,"p           print the displayed fortune\n");
  630. fprintf(a,"l           toggle long fortunes mode\n");
  631. fprintf(a,"n           select a numbered fortune\n");
  632. fprintf(a,"s           say the displayes fortune\n");
  633. fprintf(a,"i           iconise/deiconise the window\n");
  634. fprintf(a,"q           quit the program\n");
  635. fprintf(a,"other       display a new fortune\n");
  636. fprintf(a,"\n\n\nTool types for the fortune tool\n");
  637. fprintf(a,"DEFAULT=f   set default data file to f\n");
  638. fprintf(a,"DELAY=d     set delay to d seconds\n");
  639. fprintf(a,"COLOUR=c    set background colour (note English spelling!)\n");
  640. fprintf(a,"FONT=f/s    set font to font f at size s, e.g. topaz/8\n");
  641. fprintf(a,"FLAGS=TINY  use a tiny form of the icon\n");
  642. fprintf(a,"FLAGS=SPEAK set speech on\n");
  643. fprintf(a,"FLAGS=ICON  start up as an icon\n");
  644. fprintf(a,"FLAGS=LONG  long fortunes only\n");
  645. fprintf(a,"FLAGS=QUIT  quit after a delay\n");
  646. fprintf(a,"FLAGS=CLOCK display the time\n");
  647. fprintf(a,"FLAGS=DATE  display the date\n");
  648. fprintf(a,"FLAGS=ALLMEM   display available FAST and CHIP memory\n");
  649. fprintf(a,"FLAGS=TOTALMEM display total available memory\n");
  650.  
  651. fprintf(a,"The above flags can be combined, e.g. FLAGS=SPEAK|ICON\n");
  652. fclose(a);
  653. }
  654.  
  655. /* write a single line of text */
  656. int yposition=0;
  657.  
  658. VOID WrtConsole(string,len)
  659. STRPTR string;
  660. ULONG len;
  661. {
  662.     if(!yposition)yposition=ConsoleWindow->BorderTop+sysfont->tf_YSize*2;
  663.     Move(ConsoleWindow->RPort,5,yposition);
  664.     Text(ConsoleWindow->RPort,string,len);
  665.     yposition+=sysfont->tf_YSize;
  666. }
  667.  
  668. /*
  669.  * Message printing routine
  670.  * Prints a SINGLE LINE (for the time being) message in a slab
  671.  */
  672.  
  673. char msg_buf[MAXSIZE];
  674.  
  675. void Message(char *a)
  676. {
  677.     char *i,*j;
  678.  
  679.     yposition=0;
  680.  
  681.     SetAPen(ConsoleWindow->RPort,colour);
  682.     SetBPen(ConsoleWindow->RPort,colour);
  683.  
  684.     RectFill(ConsoleWindow->RPort,
  685.     ConsoleWindow->BorderLeft,
  686.     ConsoleWindow->BorderTop,
  687.     ConsoleWindow->Width-ConsoleWindow->BorderRight-1,
  688.     ConsoleWindow->Height-ConsoleWindow->BorderBottom-1);
  689.  
  690.     SetAPen(ConsoleWindow->RPort,1);
  691.     for(i=a,j=a;;j++)
  692.     {
  693.         if(*j=='\n'||!*j)
  694.         {
  695.             char c;
  696.  
  697.             c=*j; *j=0;
  698.             WrtConsole(i,j-i);
  699.             if(!(*(i=j)=c))break;
  700.             i++;
  701.         }
  702.     }
  703. }
  704.  
  705. struct TextFont *GFont(char *buf)    /* font in form "font/size" */
  706. {
  707.     int i,size;
  708.     char buf2[30],*s=NULL;
  709.     struct TextFont *tfont;
  710.     struct TextAttr ta;
  711.  
  712.     for(i=0;i<strlen(buf);i++)
  713.     {
  714.         if(buf[i]=='/')
  715.         {
  716.             buf[i]=NULL;s=buf+i+1;break;
  717.         }
  718.     }
  719.     if(!s)return(NULL);
  720.     strcpy(buf2,buf);
  721.     strcat(buf2,".font");
  722.     size=atoi(s);
  723.  
  724.     if(!(DiskfontBase=OpenLibrary("diskfont.library",0L)))return(NULL);
  725.     ta.ta_Name=buf2;
  726.     ta.ta_YSize=size;
  727.     ta.ta_Flags=FPF_DISKFONT;
  728.     ta.ta_Style=FS_NORMAL;
  729.     tfont=(struct TextFont *)OpenDiskFont(&ta);
  730.     CloseLibrary(DiskfontBase);
  731.  
  732.     return(tfont);
  733. }
  734.  
  735. VOID OpenAll()
  736. {
  737.     if(!(IntuitionBase=OpenLibrary("intuition.library",0)))
  738.         Panic(1,"unable to open intuition.library\n");
  739.  
  740.     if(!(GfxBase=OpenLibrary("graphics.library",0)))
  741.         Panic(1,"unable to open graphics.library\n");
  742.  
  743.     if(!(IconBase=OpenLibrary("icon.library",0)))
  744.         Panic(1,"unable to open icon.library\n");
  745.  
  746.     ReqToolsBase=OpenLibrary(REQTOOLSNAME,REQTOOLSVERSION);
  747. }
  748.  
  749. VOID CreateConsole(x,y,w,h)
  750. SHORT x,y,w,h;
  751. {
  752.     struct Gadget *g;
  753.     int xo,i;
  754.  
  755.     if(ConsoleOpen==TRUE)
  756.         return;
  757.  
  758.     ConNewWindow.LeftEdge=x; ConNewWindow.TopEdge=y;
  759.     ConNewWindow.Width=w; ConNewWindow.Height=h;
  760.  
  761.     if((ConsoleWindow=OpenWindow(&ConNewWindow))==NULL)
  762.         Panic(1,"can't open window\n");
  763.  
  764.     xo=(tiny&&back) ? TINYXOFFSET:XOFFSET;
  765.  
  766.     for(i=0,g=&LeftGadg;g;g=g->NextGadget)
  767.             g->LeftEdge=xo+16*i++;
  768.  
  769.     clockpos=xo+16*i+10;
  770.  
  771.     AddGList(ConsoleWindow,&LeftGadg,0,-1,NULL);
  772.  
  773.     if(customfont)
  774.         SetFont(ConsoleWindow->RPort,customfont)
  775.     ConsoleOpen=TRUE;
  776. }
  777.  
  778. VOID CleanUpConsole()
  779. {
  780.     struct Message *msg;
  781.     if(ConsoleOpen)
  782.     {
  783.         ConsoleOpen=FALSE;
  784.         if(ConsoleWindow!=NULL)
  785.         {
  786.             while(msg=GetMsg(ConsoleWindow->UserPort))ReplyMsg(msg);
  787.             CloseWindow(ConsoleWindow);
  788.         }
  789.     }
  790. }
  791.  
  792. VOID CleanUp()
  793. {
  794.     TimerStop();
  795.     SND_Shutdown();
  796.     CleanUpConsole();
  797.  
  798.     if(customfont)CloseFont(customfont);
  799.     if(GfxBase)CloseLibrary(GfxBase);
  800.     if(IntuitionBase)CloseLibrary(IntuitionBase);
  801.     if(IconBase)CloseLibrary(IconBase);
  802.     if(ReqToolsBase)CloseLibrary(ReqToolsBase);
  803. }
  804.  
  805. VOID CleanUpAndExit()
  806. {
  807.     CleanUp();
  808.     exit(TRUE);
  809. }
  810. /*
  811. void WaitForIDCMP(msg)
  812. ULONG msgc;
  813. {
  814.     struct IntuiMessage  *msg;
  815.  
  816. waitlp:    WaitPort(ConsoleWindow->UserPort);
  817.     msg=(struct IntuiMessage *)GetMsg(ConsoleWindow->UserPort);
  818.     ReplyMsg((struct Message *)msg);
  819.     if(msg->Class!=msgc)goto waitlp;
  820. }
  821. */
  822. VOID Iconise()
  823. {
  824.     back=1;
  825.  
  826.     iy=ConsoleWindow->TopEdge;
  827.  
  828.     CleanUpConsole();
  829.     CreateConsole(ix,iy,tiny?TINYICONLEN+(clock?CLOCKLEN:0):
  830.         ICONLEN+(clock?CLOCKLEN:0),9);
  831.     if((ConsoleWindow->BorderTop-9)!=0)
  832.     {
  833.         SizeWindow(ConsoleWindow,0,
  834.             ConsoleWindow->BorderTop-9);
  835.         Delay(5);
  836.     }
  837.     SetWindowTitles(ConsoleWindow,tiny?NULL:ICONTITLE,-1);
  838. }
  839.  
  840. VOID DeIconise()
  841. {
  842.     back=0;
  843.     iy=min(ConsoleWindow->TopEdge,180);
  844.     ix=ConsoleWindow->LeftEdge;
  845.     CleanUpConsole();
  846. }
  847.  
  848. void DoAnother(void)
  849. {
  850.     if(back)
  851.     {
  852.         DeIconise();
  853.     }
  854.     Ticks=0;
  855.     Again=TRUE;
  856.     return;
  857. }
  858.  
  859. int fortune_number=-1,current_fortune=0;
  860. unsigned long number;
  861. VOID GetNumber()
  862. {
  863.     char buf[80];
  864.     FILE *a;
  865.     long num;
  866.  
  867.     if(ReqToolsBase)
  868.     {
  869.         ULONG tags[]={ RTEZ_DefaultResponse,1,TAG_END};
  870.  
  871. retr1:    if(!rtGetLong(&num,"Get fortune number",NULL,
  872.         RTGL_ShowDefault,FALSE,
  873.         TAG_END))
  874.         {
  875.             if(rtEZRequest("You entered nothing.\n"
  876.                 "There are %ld fortunes.","Try again|Sorry",NULL,
  877.                 (struct TagItem *)tags,number))goto retr1;
  878.         }
  879.         else
  880.             fortune_number=num;
  881.     }
  882.     else
  883.     {
  884.         if(!(a=fopen("CON:0/0/640/40/Which fortune would you like?","r+")))
  885.         Panic(1,"unable to open getnumber window\n");
  886.         fgets(buf,40,a);
  887.         fortune_number=atoi(buf);
  888.     }
  889.     fclose(a);
  890. }
  891.  
  892. /*
  893.  * Alarm states:
  894.  *
  895.  * 0    no alarm (goes to 1 when alarm set by user)
  896.  * 1    alarm set (alarm snds and goes to 0 when alarm time = clock time)
  897.  *
  898.  */
  899.  
  900. int alarm_hour,alarm_min;
  901. int alarm_state=0;
  902.  
  903. VOID SetAlarm()
  904. {
  905.     FILE *a;
  906.     char buf[44];
  907.     int n;
  908.  
  909.     if(!clock)
  910.     {
  911.         Panic(0,"clock not active (run with -oc or FLAGS=CLOCK)");
  912.         return;
  913.     }
  914.     SND_Init();
  915.     if(!ReqToolsBase)
  916.     {
  917.         if(!(a=fopen("CON:0/0/640/40/Enter the time (HH:MM):","r+")))
  918.             Panic(1,"unable to open setalarm window\n");
  919.     }
  920.     do
  921.     {
  922.         if(ReqToolsBase)
  923.         {
  924.             *buf='\0';
  925.             rtGetString(buf,40,"Enter time (HH:MM):",NULL,TAG_END);
  926.         }
  927.         else
  928.         {
  929.             fgets(buf,40,a);
  930.         }
  931.         n=sscanf(buf,"%d:%d",&alarm_hour,&alarm_min);
  932.     } while(n<2);
  933.  
  934.     fclose(a);
  935.     alarm_state=1;
  936.     clock |= CF_CLOCK;
  937. }
  938.  
  939. void WriteFortune(char *fl,char *str)
  940. {
  941.     FILE *a;
  942.  
  943.     if(!(a=fopen(fl,"w")))return;
  944.     if(ConsoleOpen)ModifyIDCMP(ConsoleWindow,NULL);
  945.     fputs(str,a);
  946.     fclose(a);
  947.     if(ConsoleOpen)ModifyIDCMP(ConsoleWindow,IDCMPFLAGS);
  948. }
  949.  
  950. VOID WriteClock()
  951. {
  952.     static char clockbuf[80];
  953.     static char buf[20];
  954.     struct tm *ts;
  955.     static long t;
  956.     ULONG chipmem,fastmem;
  957.     char *i;
  958.     int j=0,lim;
  959.  
  960.     time(&t);
  961.     ts=localtime(&t);
  962.  
  963.     /* There is a limit on how many options the icon can show */
  964.  
  965.     lim=back?2:8;
  966.  
  967.     *clockbuf=*buf=NULL;
  968.  
  969.     if(clock & CF_CLOCK)
  970.     {
  971.         if(j++>lim)goto too_many;
  972.         sprintf(buf,"%d:%2d:%2d",ts->tm_hour,ts->tm_min,ts->tm_sec);
  973.         switch(alarm_state)
  974.         {
  975.             case 0:break;
  976.             case 1:
  977.                 if(alarm_hour==ts->tm_hour && alarm_min==ts->tm_min)
  978.                 {
  979.                     SND_Play(SoundData,SOUND_LEN,400);
  980.                     alarm_state=0;
  981.                 }
  982.                 break;
  983.             default:Panic(1,"Bad internal alarm state");
  984.         }
  985.         for(i=buf;*i;i++)if(*i==' ')*i='0';
  986.         strcat(clockbuf,buf);if(j++>lim)goto too_many;
  987.     }
  988.     if(clock & CF_DATE)
  989.     {
  990.         if(j++>lim)goto too_many;
  991.         sprintf(buf," %d:%s:%d",ts->tm_mday,
  992.             month_names[ts->tm_mon],ts->tm_year%100);
  993.         strcat(clockbuf,buf);if(j++>lim)goto too_many;
  994.     }
  995.     if(clock & CF_TOTALMEM)
  996.     {
  997.         if(j++>lim)goto too_many;
  998.         chipmem=AvailMem(0L)>>10;    /* show in K */
  999.         sprintf(buf," Mem:%ld",chipmem);
  1000.         strcat(clockbuf,buf);
  1001.     }
  1002.     if(clock & CF_ALLMEM)
  1003.     {
  1004.         if(j++>lim)goto too_many;
  1005.         chipmem=AvailMem(MEMF_CHIP)>>10;
  1006.         fastmem=AvailMem(MEMF_FAST)>>10;
  1007.         sprintf(buf," C%ld/F%ld",chipmem,fastmem);
  1008.         strcat(clockbuf,buf);
  1009.     }
  1010. too_many:
  1011.  
  1012.     strcat(clockbuf," ");
  1013.     SetFont(ConsoleWindow->RPort,topazfont);
  1014.     if(back)
  1015.     {
  1016.         SetAPen(ConsoleWindow->RPort,1);
  1017.         SetBPen(ConsoleWindow->RPort,0);
  1018.         Move(ConsoleWindow->RPort,clockpos,8);
  1019.     }
  1020.     else
  1021.         Move(ConsoleWindow->RPort,5,ConsoleWindow->Height-10);
  1022.     Text(ConsoleWindow->RPort,clockbuf,strlen(clockbuf));
  1023.     if(customfont)SetFont(ConsoleWindow->RPort,customfont);
  1024. }
  1025.  
  1026. void About()
  1027. {
  1028.     rtEZRequestTags("Fortune 3.25, by Jim Finnis (March 1993)\n"
  1029.         "Thanks to Nico Francois for ReqTools,\n"
  1030.         "to Bach, Cardiacs and R.E.M. for sonic\n"
  1031.         "debugging assistance, and to Shona\n"
  1032.         "for not minding when I crawl into bed\n"
  1033.         "at 4 AM.\n"
  1034.         "   -- White the Ergodic Archwizard","Cosmic|Virtual|Mu",
  1035.         NULL,NULL,
  1036.         RT_ReqPos,REQPOS_CENTERSCR,
  1037.         TAG_END);
  1038. }
  1039.  
  1040. VOID IDCMP_Handler()
  1041. {
  1042.     SHORT flag=TRUE;
  1043.     struct IntuiMessage *msg;
  1044.     struct Gadget *g;
  1045.     int c,code;
  1046.     USHORT id;
  1047.     ULONG signals,consolebit,timerbit=0L;
  1048.  
  1049.     consolebit=1L<<ConsoleWindow->UserPort->mp_SigBit;
  1050.     if(timerport)timerbit=1<<timerport->mp_SigBit;
  1051.  
  1052.     while(flag)
  1053.     {
  1054.         struct Message *tmsg;
  1055.  
  1056.         signals=Wait(consolebit | timerbit);
  1057.         while(msg=(struct IntuiMessage *)GetMsg(ConsoleWindow->UserPort))
  1058.         {
  1059.             c=msg->Class;
  1060.             g=(struct Gadget *)msg->IAddress;    /* only valid for gadg. */
  1061.             code=msg->Code;
  1062.             ReplyMsg((struct Message *)msg);
  1063.  
  1064.             switch(c)
  1065.             {
  1066.             case CLOSEWINDOW:
  1067.                 flag=FALSE;
  1068.                 break;
  1069.             case VANILLAKEY:
  1070.                 switch(code)
  1071.                 {
  1072.                     case 'p':
  1073.                         print=1;
  1074.                         flag=FALSE;
  1075.                         DoAnother();
  1076.                         break;
  1077.                     case 's':
  1078.                         flag=FALSE;
  1079.                         DoAnother();
  1080.                         speak=!speak;
  1081.                         break;
  1082.                     case 'l':
  1083.                         flag=FALSE;
  1084.                         DoAnother();
  1085.                         longflag=!longflag;
  1086.                         break;
  1087.                     case 'q':
  1088.                         if(ReqToolsBase)
  1089.                         {
  1090.                             if(rtEZRequest("Really quit this awesome program?",
  1091.                                 "Way|No way!",NULL,NULL))flag=FALSE;
  1092.                         }
  1093.                         else
  1094.                             flag=FALSE;
  1095.                         break;
  1096.                     case 'i':
  1097.                         if(back)
  1098.                             DeIconise();
  1099.                         else
  1100.                         {
  1101.                             Iconise();
  1102.                             break;
  1103.                         }
  1104.                         Ticks=0;
  1105.                         flag=FALSE;
  1106.                         Again=TRUE;
  1107.                         break;
  1108.                     case 'n':
  1109.                         GetNumber();
  1110.                         flag=FALSE;
  1111.                         DoAnother();
  1112.                         break;
  1113.                     case 'a':
  1114.                         SetAlarm();
  1115.                         break;
  1116.                     case '?':About();break;
  1117.                     default:
  1118.                         flag=FALSE;
  1119.                         DoAnother();
  1120.                         break;
  1121.                 }
  1122.                 break;
  1123.             case GADGETDOWN:
  1124.                 id=g->GadgetID;
  1125.                 switch(id)
  1126.                 {
  1127.                     case 0: /* left */
  1128.                         fortune_number=current_fortune-1;
  1129.                         fortune_number=max(fortune_number,0);
  1130.                         flag=FALSE; DoAnother(); break;
  1131.                     case 1: /* rand */
  1132.                         flag=FALSE; DoAnother(); break;
  1133.                     case 2: /*right */
  1134.                         fortune_number=current_fortune+1;
  1135.                         fortune_number=min(fortune_number,(number-1));
  1136.                         flag=FALSE; DoAnother(); break;
  1137.                     case 3:    /* pause */
  1138.                         break;
  1139.                     case 4:    /* iconify */
  1140.                         if(back)
  1141.                             DeIconise();
  1142.                         else
  1143.                         {
  1144.                             Iconise();break;
  1145.                         }
  1146.                         Ticks=0;flag=FALSE;    Again=TRUE;
  1147.                         break;
  1148.                     default:Panic(1,"Funny gadget - %d\n!",id);
  1149.                 }
  1150.  
  1151.             default:
  1152.                 break;
  1153.             } /* switch */
  1154.             if(!ConsoleOpen)
  1155.                 break;
  1156.         } /* while */
  1157.         while(tmsg=GetMsg(timerport))
  1158.         {
  1159.             if(clock&&ConsoleOpen)WriteClock();
  1160.             TimerGo();    /* and kick it again */
  1161.             if(back||PauseGadg.Flags & SELECTED)break;
  1162.             if(Ticks++>del){Ticks=0;Again=TRUE;flag=FALSE;}
  1163.         }
  1164.     } /* while */
  1165. }
  1166.  
  1167. void __regargs main(int argc,char *argv[])
  1168. {
  1169.     char *inf=infile;
  1170.     int ow=0,w,oh=0,r,i,h,slen;
  1171.     char buf[MAXSIZE],ermintrude[80];
  1172.     char *str;
  1173.     char snum[30];
  1174.     int maxsize,maxwinsize,scrwidth=640,scrheight=200;
  1175.     int winposx=30,winposy=0,usageflag=0,quit_delay=0;
  1176.     unsigned long pos,t;
  1177.     BPTR a;
  1178.     FILE *fa;
  1179.     struct WBArg *wbarg;
  1180.     struct WBStartup *WBenchMsg;
  1181.     struct Screen *wbscr;
  1182.  
  1183.     OpenAll();
  1184.  
  1185.     if(wbscr=OpenWorkBench())
  1186.     {
  1187.         scrwidth=wbscr->Width;
  1188.         scrheight=wbscr->Height;
  1189.     }
  1190.  
  1191.     topazfont=sysfont=GfxBase->DefaultFont;
  1192.     maxsize=maxwinsize=scrheight;
  1193.  
  1194.     srand(time(&t));
  1195.     if(argc)
  1196.     {
  1197.         wb_exec=0;
  1198.         if((argc>1) && (!strcmp(argv[1],"?")))
  1199.             usageflag=1;
  1200.  
  1201.         for(i=1;i<argc;++i)
  1202.         {
  1203.             switch(argv[i][1])
  1204.             {
  1205.                 case 'o':
  1206.                 case 'O':    /* what clock stuff do we get?
  1207.                             Note that only the first two of these have
  1208.                             any effect */
  1209.                     for(str=argv[i]+2;*str;str++)
  1210.                     {
  1211.                         switch(*str)
  1212.                         {
  1213.                             case 'c':clock |= CF_CLOCK;break;
  1214.                             case 'd':clock |= CF_DATE;break;
  1215.                             case 'm':clock |= CF_ALLMEM;break;
  1216.                             case 't':clock |= CF_TOTALMEM;break;
  1217.                         }
  1218.                     }
  1219.                     break;
  1220.                 case 'q':
  1221.                 case 'Q':
  1222.                     quit_delay=1;
  1223.                     break;
  1224.                 case 'n':
  1225.                 case 'N':
  1226.                     fortune_number=atoi(argv[i]+2);
  1227.                     break;
  1228.                 case 'f':
  1229.                 case 'F':
  1230.                     strcpy(ermintrude,argv[i]+2);
  1231.                     inf=ermintrude;
  1232.                     break;
  1233.                 case 'l':    /* >10 line fortunes only */
  1234.                 case 'L':
  1235.                     longflag=1;break;
  1236.                 case 'i':    /* Iconise */
  1237.                 case 'I':
  1238.                     back=1;
  1239.                     break;
  1240.                 case 't':    /* tiny icon */
  1241.                 case 'T':
  1242.                     tiny=1;break;
  1243.                 case 'w':    /* Window it anyway. */
  1244.                 case 'W':
  1245.                     win=1;
  1246.                     break;
  1247.                 case 'c':
  1248.                 case 'C':
  1249.                     colour=atoi(argv[i]+2);
  1250.                     break;
  1251.                 case 'd':     /* delay */
  1252.                 case 'D':
  1253.                     del=atoi(argv[i]+2);
  1254.                     del=max(2,del);
  1255.                     break;
  1256.                 case 'm':    /* maxsize of window */
  1257.                 case 'M':
  1258.                     maxsize=atoi(argv[i]+2);
  1259.                     maxsize=min(maxwinsize,maxsize);
  1260.                     maxsize=max(20,maxsize);
  1261.                     break;
  1262.                 case 's':    /* speech (titter) */
  1263.                     speak=1;
  1264.                     break;
  1265.                 case 'y':    /* position of window */
  1266.                 case 'Y':
  1267.                 case 'p':
  1268.                 case 'P':
  1269.                     winposy=atoi(argv[i]+2);
  1270.                     winposy=min(maxwinsize-20,winposy);
  1271.                     winposy=max(0,winposy);
  1272.                     break;
  1273.                 case 'x':    /* position of window */
  1274.                 case 'X':
  1275.                     winposx=atoi(argv[i]+2);
  1276.                     winposx=min(640-ICONLEN+CLOCKLEN,winposx);
  1277.                     winposx=max(0,winposx);
  1278.                     break;
  1279.  
  1280.                 case 'H':
  1281.                 case 'h':
  1282.                 case '?':
  1283.                     usageflag=1;
  1284.                     break;
  1285.  
  1286.             }
  1287.         }
  1288.     }
  1289.     else    /* WB Startup */
  1290.     {
  1291.         struct DiskObject *dobj;
  1292.         char *quop;
  1293.         char **toolarray;
  1294.  
  1295.         win=1;
  1296.         WBenchMsg=(struct WBStartup *)argv;
  1297.  
  1298.         wbarg=WBenchMsg->sm_ArgList;
  1299.  
  1300.         if((*wbarg->wa_Name)&&(dobj=GetDiskObject(wbarg->wa_Name)))
  1301.         {
  1302.             toolarray=(char **)dobj->do_ToolTypes;
  1303.             if(quop=(char *)FindToolType(toolarray,"DEFAULT"))
  1304.             {
  1305.                 strcpy(ermintrude,quop);
  1306.                 inf=ermintrude;
  1307.             }
  1308.             if(quop=(char *)FindToolType(toolarray,"FONT"))
  1309.             {
  1310.                 strcpy(buf,quop);
  1311.                 if(customfont=GFont(buf))
  1312.                     sysfont=customfont;
  1313.             }
  1314.  
  1315.             if(quop=(char *)FindToolType(toolarray,"DELAY"))
  1316.             {
  1317.                 del=atoi(quop);
  1318.                 del=max(del,1);
  1319.             }
  1320.             if(quop=(char *)FindToolType(toolarray,"COLOUR"))
  1321.                 colour=atoi(quop);
  1322.             if(quop=(char *)FindToolType(toolarray,"FLAGS"))
  1323.             {
  1324.                 if(MatchToolValue(quop,"SPEAK"))
  1325.                     speak=1;
  1326.                 if(MatchToolValue(quop,"LONG"))
  1327.                     longflag=1;
  1328.                 if(MatchToolValue(quop,"TINY"))
  1329.                     tiny=1;
  1330.                 if(MatchToolValue(quop,"ICON"))
  1331.                     back=1;
  1332.                 if(MatchToolValue(quop,"QUIT"))
  1333.                     quit_delay=1;
  1334.                 if(MatchToolValue(quop,"CLOCK"))
  1335.                     clock|=CF_CLOCK;
  1336.                 if(MatchToolValue(quop,"TOTALMEM"))
  1337.                     clock|=CF_TOTALMEM;
  1338.                 if(MatchToolValue(quop,"ALLMEM"))
  1339.                     clock|=CF_ALLMEM;
  1340.                 if(MatchToolValue(quop,"DATE"))
  1341.                     clock|=CF_DATE;
  1342.             }
  1343.             FreeDiskObject(dobj);
  1344.         }
  1345.  
  1346.         if(WBenchMsg->sm_NumArgs>=2)
  1347.         {
  1348.             wbarg=WBenchMsg->sm_ArgList+1;
  1349.             olddir=-1;
  1350.  
  1351.             if((wbarg->wa_Lock)&&(*wbarg->wa_Name))
  1352.                 olddir=CurrentDir(wbarg->wa_Lock);
  1353.             inf=wbarg->wa_Name;
  1354.  
  1355.             if((*wbarg->wa_Name)&&
  1356.                 (dobj=GetDiskObject(wbarg->wa_Name)))
  1357.             {
  1358.                 toolarray=(char **)dobj->do_ToolTypes;
  1359.                 if(quop=(char *)FindToolType(toolarray,
  1360.                 "FILETYPE"))
  1361.                 {
  1362.                     if(strcmp(quop,"Fortunes"))
  1363.                         inf=NULL;
  1364.                 }
  1365.                 else
  1366.                     inf=NULL;
  1367.                 FreeDiskObject(dobj);
  1368.             }
  1369.         }
  1370.         if(!inf)
  1371.         {
  1372.             DisplayBeep(NULL);
  1373.             CleanUpAndExit();
  1374.         }
  1375.     }
  1376.  
  1377.     if(quit_delay)back=0;    /* can't have an iconised quitter! */
  1378.     if(del<0)
  1379.         del=quit_delay?60:TIMELIM;
  1380.  
  1381.     iy=winposy;
  1382.     ix=winposx;
  1383.  
  1384.     if(usageflag)
  1385.     {
  1386.         PrintUsage();
  1387.         CleanUpAndExit();
  1388.     }
  1389.  
  1390.     /* This is the beginning of the main loop. The file is reopened, because
  1391.     rewind() in Lattice's library is flaky. */
  1392.  
  1393. giles:
  1394.  
  1395.     NiceUp();
  1396.  
  1397.     if(!(a=Open(inf,MODE_OLDFILE)))
  1398.             Panic(1,"File not found - %s\n",inf);
  1399.  
  1400.     /* read in the huffman table */
  1401.  
  1402.     loadhuffman(a);
  1403.  
  1404.     /* How many fortunes are there? */
  1405.  
  1406.     number=readlong(a);
  1407.     if(number<=0) Panic(1,"Bad data file\n");
  1408.  
  1409.     /* Get a random one */
  1410.  
  1411.     current_fortune = fortune_number<0 ?
  1412.         rand()%((unsigned int)number):fortune_number;
  1413.  
  1414.     if(current_fortune>=number)
  1415.     {
  1416.         Panic(0,"Fortune %d out of range, there are %d fortunes\n",
  1417.             current_fortune,number);
  1418.         fortune_number=-1;
  1419.         goto giles;
  1420.     }
  1421.  
  1422.     sprintf(snum,"Fortune number #%d",current_fortune);
  1423.     ConNewWindow.Title=snum;
  1424.     ConNewWindow.MaxHeight=maxsize;
  1425.  
  1426.     /* Get the position */
  1427.     Seek(a,4*(current_fortune+1)+20*16,OFFSET_BEGINNING);
  1428.     pos=readlong(a);
  1429.  
  1430.     /* Grab it */
  1431.  
  1432.     Seek(a,pos,OFFSET_BEGINNING);
  1433.     readstring(&buf,MAXSIZE,a);
  1434.     Close(a);
  1435.  
  1436.     str=uncompress(buf);
  1437.  
  1438.     /* How many lines of text in the fortune? */
  1439.     slen=strlen(str);
  1440.     for(r=0,i=0;i<slen;i++) if(str[i]=='\n') r++;
  1441.     if((fortune_number<0) && longflag && (r<=5))
  1442.     {
  1443.         fortune_number=-1;
  1444.         goto giles;
  1445.     }
  1446.  
  1447.     if(argc)    /* If run from CLI */
  1448.     {
  1449.         if(!win)
  1450.         {
  1451.             fa=fopen("*","r+");
  1452.             if(fa==NULL) CleanUpAndExit();
  1453.             fprintf(fa,"%s",str);
  1454.             if(speak)WriteFortune("speak:",str);
  1455.             fclose(fa);
  1456.             CleanUpAndExit(0);
  1457.         }
  1458.     }
  1459.  
  1460.     /* Work out the size of the window (use default font for 2.0) */
  1461.     h=(sysfont->tf_YSize)*(r+2)+22;
  1462.  
  1463.     if(h>maxsize)
  1464.     {
  1465.         if(fortune_number>0)
  1466.             Panic(0,"fortune too tall\n");
  1467.         fortune_number=-1;
  1468.         goto giles;
  1469.     }
  1470.  
  1471.     /* Is it too wide? */
  1472.  
  1473.     if((w=(GetMaxTextLen(sysfont,str)+10))>(scrwidth-5))
  1474.     {
  1475.         if(fortune_number>0)
  1476.             Panic(0,"fortune too wide\n");
  1477.         fortune_number=-1;
  1478.         goto giles;
  1479.     }
  1480.     w=max(w,MINWIDTH);
  1481.  
  1482.     /* Start the inexorable march of time.... */
  1483.     if(!timeropen&&win)StartTimerDevice();
  1484.  
  1485.     if(ConsoleOpen)
  1486.     {
  1487.         int deltah,deltaw;
  1488.  
  1489.         if(!back)
  1490.         {
  1491.             int p,q;
  1492.             deltah=h-oh; deltaw=w-ow;
  1493.             p=ConsoleWindow->LeftEdge+ConsoleWindow->Width+deltaw;
  1494.             q=ConsoleWindow->TopEdge+ConsoleWindow->Height+deltah;
  1495.             p=p>scrwidth?scrwidth-p:0;
  1496.             q=q>maxwinsize?maxwinsize-q:0;
  1497.             if(p||q)
  1498.                 MoveWindow(ConsoleWindow,p,q);
  1499.  
  1500.             SizeWindow(ConsoleWindow,deltaw,deltah);
  1501.             SetWindowTitles(ConsoleWindow,snum,-1);
  1502.             Delay(5);
  1503.         }
  1504.     }
  1505.     else
  1506.     {
  1507.         if(back)
  1508.         {
  1509.             CreateConsole(ix,iy,tiny?TINYICONLEN+(clock?CLOCKLEN:0):
  1510.                 ICONLEN+(clock?CLOCKLEN:0),9);
  1511.             if((ConsoleWindow->BorderTop-9)!=0)
  1512.             {
  1513.                 SizeWindow(ConsoleWindow,0,
  1514.                     ConsoleWindow->BorderTop-9);
  1515.                 Delay(5);
  1516.             }
  1517.             SetWindowTitles(ConsoleWindow,tiny?NULL:ICONTITLE,-1);
  1518.         }
  1519.         else
  1520.         {
  1521.             if(iy+h>maxwinsize)iy=maxwinsize-h;
  1522.             if(ix+w>scrwidth)ix=scrwidth-w;
  1523.             CreateConsole(ix,iy,w,h);
  1524.             if((ConsoleWindow->BorderTop-9)!=0)
  1525.             {
  1526.                 SizeWindow(ConsoleWindow,0,
  1527.                     ConsoleWindow->BorderTop-9);
  1528.                 Delay(5);
  1529.             }
  1530.         }
  1531.     }
  1532.  
  1533.     if(!back)
  1534.         Message(str);
  1535.  
  1536.     NiceDown();
  1537.  
  1538.     fortune_number=-1;
  1539.  
  1540.     if(quit_delay)    /* quit after a delay */
  1541.     {
  1542.         Delay(del*TICKS_PER_SECOND);
  1543.         CleanUpAndExit();
  1544.     }
  1545.  
  1546.     IDCMP_Handler();
  1547.  
  1548.     if(speak)
  1549.     {
  1550.         speak=0;
  1551.         WriteFortune("speak:",str);
  1552.     }
  1553.  
  1554.     if(print)
  1555.     {
  1556.         print=0;
  1557.         WriteFortune("prt:","\n");WriteFortune("prt:",str);
  1558.     }
  1559.  
  1560.     if(Again)
  1561.     {
  1562.         Again=FALSE;
  1563.         oh=h;ow=w;
  1564.         goto giles;
  1565.     }
  1566.     CleanUpAndExit();
  1567. }
  1568.  
  1569.